class URLMatcher {
  static patternToRegex(pattern) {
    if (!pattern || typeof pattern !== 'string') {
      return null;
    }

    // 先保护*号，然后转义其他特殊字符，最后将*替换为.*
    let regexStr = pattern
      .replace(/\*/g, '___WILDCARD___')  // 临时替换*号
      .replace(/[.+?^${}()|[\]\\]/g, '\\$&')  // 转义其他特殊字符
      .replace(/___WILDCARD___/g, '.*');  // 将*号替换为.*
    
    // 不强制要求开头和结尾匹配，让用户有更多灵活性
    // 如果用户想要精确匹配，可以自己添加^和$
    
    try {
      return new RegExp(regexStr, 'i');
    } catch (error) {
      return null;
    }
  }

  static isMatch(url, pattern) {
    if (!url || !pattern) {
      return false;
    }
    

    const regex = this.patternToRegex(pattern);
    if (!regex) {
      return false;
    }
    
    const result = regex.test(url);

    return result;
  }

  static getMatchingRules(url, rules) {
    if (!url || !rules || !Array.isArray(rules.urlRules)) {
      return [];
    }
    
    return rules.urlRules.filter(rule => {
      return rule.enabled && this.isMatch(url, rule.pattern);
    });
  }

  static getMatchingElementRules(url, rules) {
    const matchingUrlRules = this.getMatchingRules(url, rules);
    const elementRules = [];
    
    matchingUrlRules.forEach(urlRule => {
      if (urlRule.elementRules && Array.isArray(urlRule.elementRules)) {
        urlRule.elementRules.forEach(elementRule => {
          if (elementRule.enabled) {
            elementRules.push({
              ...elementRule,
              urlRuleId: urlRule.id,
              urlPattern: urlRule.pattern
            });
          }
        });
      }
    });
    
    return elementRules;
  }

  static validatePattern(pattern) {
    if (!pattern || typeof pattern !== 'string') {
      return { valid: false, error: 'Pattern must be a non-empty string' };
    }
    
    if (pattern.length > 2048) {
      return { valid: false, error: 'Pattern is too long (max 2048 characters)' };
    }
    
    const invalidChars = pattern.match(/[<>"|]/);
    if (invalidChars) {
      return { valid: false, error: `Invalid character: ${invalidChars[0]}` };
    }
    
    const regex = this.patternToRegex(pattern);
    if (!regex) {
      return { valid: false, error: 'Invalid pattern format' };
    }
    
    return { valid: true };
  }

  static normalizeUrl(url) {
    try {
      const urlObj = new URL(url);
      return urlObj.href;
    } catch (error) {
      return url;
    }
  }

  static extractDomain(url) {
    try {
      const urlObj = new URL(url);
      return urlObj.hostname;
    } catch (error) {
      return '';
    }
  }

  static suggestPatterns(url) {
    if (!url) {
      return [];
    }
    
    try {
      const urlObj = new URL(url);
      const suggestions = [];
      
      suggestions.push({
        pattern: urlObj.href,
        description: 'Exact URL match'
      });
      
      if (urlObj.pathname !== '/') {
        suggestions.push({
          pattern: `${urlObj.protocol}//${urlObj.host}${urlObj.pathname}*`,
          description: 'Same path with any query/hash'
        });
        
        const pathParts = urlObj.pathname.split('/').filter(part => part);
        if (pathParts.length > 1) {
          suggestions.push({
            pattern: `${urlObj.protocol}//${urlObj.host}/${pathParts[0]}/*`,
            description: 'Same first path segment'
          });
        }
      }
      
      suggestions.push({
        pattern: `${urlObj.protocol}//${urlObj.host}/*`,
        description: 'Same domain'
      });
      
      if (urlObj.hostname.startsWith('www.')) {
        const domain = urlObj.hostname.substring(4);
        suggestions.push({
          pattern: `${urlObj.protocol}//*.${domain}/*`,
          description: 'All subdomains'
        });
      } else {
        suggestions.push({
          pattern: `${urlObj.protocol}//*.${urlObj.hostname}/*`,
          description: 'All subdomains'
        });
      }
      
      const domainParts = urlObj.hostname.split('.');
      if (domainParts.length >= 2) {
        const topDomain = domainParts.slice(-2).join('.');
        suggestions.push({
          pattern: `*://*.${topDomain}/*`,
          description: 'All protocols and subdomains'
        });
      }
      
      return suggestions;
    } catch (error) {
      return [];
    }
  }

  static testPattern(pattern, testUrls = []) {
    const results = {
      pattern,
      valid: false,
      error: null,
      matches: []
    };
    
    const validation = this.validatePattern(pattern);
    if (!validation.valid) {
      results.error = validation.error;
      return results;
    }
    
    results.valid = true;
    
    testUrls.forEach(url => {
      results.matches.push({
        url,
        matches: this.isMatch(url, pattern)
      });
    });
    
    return results;
  }
}

if (typeof window !== 'undefined') {
  window.URLMatcher = URLMatcher;
}